package syncd

import (
	"../monitor"
)

type Feed struct {
	last     int64
	versions map[int64]string
	entries  map[string]int64
	monitor  monitor.Monitor
}

type Results struct {
	Version int64
	Entries []string
}

func NewFeed() *Feed {

	f := &Feed{0, make(map[int64]string), make(map[string]int64), monitor.New()}

	return f
}

func (f *Feed) next() int64 {
	i := f.last
	f.last++
	return i
}

// publishes a URI, returning new global version number
func (f *Feed) Publish(uri string) int64 {

	i := f.next()

	f.versions[i] = uri

	old, ok := f.entries[uri]

	if ok {
		// remove old entry from versions, since we no longer need it
		delete(f.versions, old)
	}

	f.entries[uri] = i

	f.monitor.Signal()

	return i
}

func (f *Feed) Wait() {
	f.monitor.Wait()
}

func (f *Feed) Since(since int64) (Results, bool) {

	// max number of new elements
	n := f.last - since

	if n < 0 {
		n = -n
	}

	// backing array
	buf := make([]string, n)

	entries := buf[0:0]

	for i := since; i < f.last; i++ {
		// find new entries

		entry, ok := f.versions[i]

		if ok {
			entries = append(entries, entry)
		}
	}

	if len(entries) > 0 {
		return Results{f.last, entries}, true
	}

	return Results{f.last, entries}, false
}
